import React from 'react'
import Component, { mapStateToProps, mapDispatchToProps } from '@components/Component'
import { connect } from 'react-redux'
import { Dropdown, Button, Checkbox, message, Modal, Form, Input, Select } from 'antd'
import { EllipsisOutlined, ExclamationCircleOutlined } from '@ant-design/icons'
import style from './RoleAuthorities.module.less'
import { } from '@redux/actions'

const { confirm } = Modal
const { Option } = Select

const layout = {
  labelCol: { span: 6 },
  wrapperCol: { span: 18 }
}

class RoleAuthorities extends Component {
  state = {
    addModalVisible: false, // 是否显示添加角色弹框
    modifyModalVisible: false, // 是否显示修改角色弹框
    roleMap: {}, // 角色id映射对象
    roleList: [], // 角色列表
    currentRoleId: '', // 当前选择角色id
    currentRoleAuthorities: [], // 当前角色的权限列表
    modifyRole: null, // 当前修改的角色
    desktops: [], // 桌面列表
    authoritiesTree: [], // 权限树
    authoritiesTreeMap: {} // 权限树id映射对象
  }

  addFormRef = React.createRef()
  modifyFormRef = React.createRef()

  // 格式化对象为数组
  formatListFromObject (obj) {
    const keys = Object.keys(obj)
    return keys.map(key => obj[key])
  }

  // 获取角色列表
  getRoleList () {
    return this.$get('/api/admin/role', {
      appid: '111',
      page_size: 100,
      current: 1
    }).then(res => {
      if (res.status === 1) {
        const map = {}
        res.data.list.forEach(li => {
          map[li.id] = li
        })
        const obj = {
          roleMap: map,
          roleList: res.data.list
        }
        if (!this.state.currentRoleId && res.data.list[0]) {
          obj.currentRoleId = res.data.list[0].id
        }
        this.setState(obj, () => {
          this.getRoleAuthorities() // 获取当前角色的权限
        })
      } else {
        message.warning(res.message)
      }
    })
  }

  // 获取桌面列表
  getDesktops () {
    return this.$get('/api/admin/desktops', {
      appid: '111'
    })
      .then(res => {
        if (res.status === 1) {
          this.setState({
            desktops: res.data
          })
        } else {
          message.warning(res.message)
        }
      })
  }

  // 获取权限树
  getAuthoritiesTree () {
    return this.$get('/api/admin/authorities', {
      appid: '111',
      type: 'menu',
      pid: null
    }).then(res => {
      if (res.status === 1) {
        let authoritiesTree = this.formatListFromObject(res.data || {})
        authoritiesTree = authoritiesTree.map(li => {
          if (li.children) {
            li.children = this.formatListFromObject(li.children)
          }
          return li
        })
        this.setState({
          authoritiesTree,
          authoritiesTreeMap: this.getAuthoritiesTreeMap(authoritiesTree)
        })
      } else {
        message.warning(res.message)
      }
    })
  }

  // 获取初始化数据
  getInitData () {
    const hide = message.loading('加载中', 120)
    Promise.all([this.getRoleList(), this.getDesktops(), this.getAuthoritiesTree()])
      .then(res => hide())
      .catch(res => hide())
  }

  // 获取角色权限
  getRoleAuthorities () {
    const hide = message.loading('获取角色权限中', 120)
    this.$get(`/api/admin/role/${this.state.currentRoleId}`, {
      appid: '111'
    }).then(res => {
      hide()
      if (res.status === 1) {
        this.setState({
          currentRoleAuthorities: res.data.authorities || []
        })
      } else {
        message.warning(res.message)
      }
    }).catch(() => hide())
  }

  // 设置角色权限
  setRoleAuthorities (currentRoleAuthorities) {
    const hide = message.loading('设置角色权限中', 120)
    const role = Object.assign({}, this.state.roleMap[this.state.currentRoleId] || {})
    const id = role.id
    delete role.id
    delete role.desktop
    return this.$put(`/api/admin/role/${id}`, {
      ...role,
      appid: '111',
      authorities: currentRoleAuthorities
    }).then(res => {
      hide()
      if (res.status !== 1) {
        message.warning(res.message)
      } else {
        this.setState({
          currentRoleAuthorities
        })
      }
    }).catch(e => {
      hide()
      throw e
    })
  }

  // 获取权限树id映射对象
  getAuthoritiesTreeMap (list) {
    const map = {}
    list.forEach(li => {
      map[li.id] = []
      if (li.children) {
        li.children.forEach(child => {
          map[li.id].push(child.id)
        })
      }
    })
    return map
  }

  // 更改单个权限状态
  toggleAuthority (pid, id, checked) {
    if (!this.state.currentRoleId) {
      return false
    }
    const currentRoleAuthorities = this.state.currentRoleAuthorities.slice()
    const pures = currentRoleAuthorities.filter(i => [pid, id].indexOf(i) === -1) // 排除当前权限和其父权限的id
    const authorities = this.state.authoritiesTreeMap[pid] || [] // 当前权限的父权限的所有子权限
    const otherIds = authorities.filter(i => i !== id) // 除去当前权限后的父权限的子权限
    const hasCheckedOther = pures.some(i => otherIds.indexOf(i) !== -1) // 是否有其他权限被选中
    if (!checked) {
      pures.push(pid)
      pures.push(id)
    } else if (hasCheckedOther) {
      pures.push(pid)
    }
    this.setRoleAuthorities(pures)
  }

  // 更改一组权限状态
  toggleAuthorities (id, checked) {
    if (!this.state.currentRoleId) {
      return false
    }
    const authorities = [...(this.state.authoritiesTreeMap[id] || [])]
    authorities.push(id)
    let currentRoleAuthorities = this.state.currentRoleAuthorities.filter(i => authorities.indexOf(i) === -1)
    if (!checked) {
      currentRoleAuthorities = [...currentRoleAuthorities, ...authorities]
    }
    this.setRoleAuthorities(currentRoleAuthorities)
  }

  // 设置当前角色
  setCurrentRole (id) {
    this.setState({
      currentRoleId: id
    }, () => {
      this.getRoleAuthorities()
    })
  }

  // 确定添加角色回调
  addRoleHandle () {
    this.addFormRef.current.submit()
  }

  // 取消添加角色回调
  cancelAdd () {
    this.addFormRef.current.resetFields()
    this.setState({
      addModalVisible: false
    })
  }

  // 确定修改角色回调
  modifyRoleHandle () {
    this.modifyFormRef.current.submit()
  }

  // 取消修改角色回调
  cancelModify () {
    this.modifyFormRef.current.resetFields()
    this.setState({
      modifyModalVisible: false
    })
  }

  // 点击添加角色按钮回调
  addButtonHandle () {
    this.addFormRef.current.resetFields()
    this.setState({
      addModalVisible: true
    })
  }

  // 点击修改角色按钮回调
  modifyRoleButtonHandle (id) {
    const role = Object.assign({}, this.state.roleMap[id] || {})
    this.setState({
      modifyModalVisible: true,
      modifyRole: role
    }, () => {
      this.modifyFormRef.current.resetFields()
    })
  }

  // 添加角色请求
  addRoleRequest (name) {
    const hide = message.loading('添加中', 120)
    this.$post('/api/admin/role', {
      name,
      authorities: [],
      appid: '111'
    }).then(res => {
      hide()
      if (res.status === 1) {
        this.getRoleList()
        this.setState({
          addModalVisible: false
        })
      } else {
        message.warning(res.message)
      }
    }).catch(() => hide())
  }

  // 修改角色请求
  modifyRoleRequest (data) {
    const hide = message.loading('添加中', 120)
    const id = data.id
    delete data.id
    this.$put(`/api/admin/role/${id}`, {
      ...data,
      appid: '111'
    }).then(res => {
      hide()
      if (res.status === 1) {
        this.getRoleList()
        this.setState({
          modifyModalVisible: false
        })
      } else {
        message.warning(res.message)
      }
    }).catch(() => hide())
  }

  // 删除角色按钮回调
  delRoleHandle (id) {
    const role = Object.assign({}, this.state.roleMap[id] || {})
    confirm({
      title: '提示',
      icon: <ExclamationCircleOutlined />,
      content: `您确定要删除 ${role.name} 吗？`,
      onOk: () => {
        this.delRoleRequest(id)
      }
    })
  }

  // 删除角色请求
  delRoleRequest (id) {
    const hide = message.loading('删除角色中', 120)
    this.$delete(`/api/admin/role/${id}`, {
      appid: id
    }).then(res => {
      hide()
      if (res.status === 1) {
        if (this.state.currentRoleId === id) {
          this.setState({
            currentRoleId: ''
          }, () => {
            this.getRoleList()
          })
        }
      } else {
        message.warning(res.message)
      }
    }).catch(() => hide())
  }

  componentDidMount () {
    this.getInitData()
  }

  // 生成角色操作菜单
  renderMenu (id) {
    return {
      items: [
        { label: '修改', key: 0, onClick: () => { this.modifyRoleButtonHandle(id) } },
        { label: '删除', key: 1, danger: true, onClick: () => { this.delRoleHandle(id) } }
      ]
    }
  }

  // 渲染角色列表
  renderRoleList () {
    return this.state.roleList.map(li => {
      let classname = ''
      if (li.id === this.state.currentRoleId) {
        classname = style.active
      }
      return (
        <li className={classname} key={li.id}>
          <div onClick={() => this.setCurrentRole(li.id)}>{li.name}</div>
          <Dropdown menu={this.renderMenu(li.id)} trigger={['click']} onClick={e => e.stopPropagation()}>
            <i>
              <EllipsisOutlined />
            </i>
          </Dropdown>
        </li>
      )
    })
  }

  // 渲染权限树
  renderAuthoritiesList () {
    const { authoritiesTreeMap, currentRoleAuthorities, currentRoleId } = this.state
    return this.state.authoritiesTree.map(li => {
      const totalList = authoritiesTreeMap[li.id] || []
      const status = {
        checked: totalList.every(id => currentRoleAuthorities.indexOf(id) !== -1),
        disabled: !currentRoleId
      }
      if (!status.checked) {
        status.indeterminate = totalList.some(id => currentRoleAuthorities.indexOf(id) !== -1)
      }
      return (
        <div key={li.id} className={style['authorities-block']}>
          <div className={style['authorities-top']} onClick={() => this.toggleAuthorities(li.id, status.checked)}>
            <Checkbox {...status} />
            <span className={style['authorities-top-title']}>{li.name}</span>
          </div>
          <div className={style['authorities-list']}>
            {this.renderAuthoritiesLeaf(li.children)}
          </div>
        </div>
      )
    })
  }

  // 渲染权限项
  renderAuthoritiesLeaf (list) {
    if (!list) {
      list = []
    }
    return list.map(li => {
      const status = {
        checked: this.state.currentRoleAuthorities.indexOf(li.id) !== -1,
        disabled: !this.state.currentRoleId
      }
      return (
        <div key={li.id} className={style['authorities-cell']} onClick={() => this.toggleAuthority(li.pid, li.id, status.checked)}>
          <span>{li.name}</span>
          <Checkbox {...status} />
        </div>
      )
    })
  }

  renderAddModal () {
    return (
      <Modal
        title='添加角色'
        forceRender
        open={this.state.addModalVisible}
        maskClosable={false}
        onOk={() => this.addRoleHandle()}
        onCancel={() => this.cancelAdd()}
      >
        <Form name='add' ref={this.addFormRef} {...layout} onFinish={v => this.addRoleRequest(v.name)}>
          <Form.Item name='name' label='角色' rules={[{ required: true, message: '角色不能为空' }]}>
            <Input />
          </Form.Item>
          <Form.Item name='desktop' label='桌面'>
            <Select placeholder='请选择桌面'>
              {
                this.state.desktops.map(li => (
                  <Option key={li.id}>{li.name}</Option>
                ))
              }
            </Select>
          </Form.Item>
        </Form>
      </Modal>
    )
  }

  renderModifyModal () {
    return (
      <Modal
        forceRender
        title='修改角色'
        open={this.state.modifyModalVisible}
        maskClosable={false}
        onOk={() => this.modifyRoleHandle()}
        onCancel={() => this.cancelModify()}
      >
        <Form name='modify' ref={this.modifyFormRef} {...layout} onFinish={v => this.modifyRoleRequest(v)} initialValues={this.state.modifyRole}>
          <Form.Item noStyle name='id'><span /></Form.Item>
          <Form.Item noStyle name='appid'><span /></Form.Item>
          <Form.Item noStyle name='status'><span /></Form.Item>
          <Form.Item noStyle name='authorities'><span /></Form.Item>
          <Form.Item name='name' label='角色' rules={[{ required: true, message: '角色不能为空' }]}>
            <Input />
          </Form.Item>
          <Form.Item name='desktop' label='桌面'>
            <Select placeholder='请选择桌面'>
              {
                this.state.desktops.map(li => (
                  <Option key={li.id}>{li.name}</Option>
                ))
              }
            </Select>
          </Form.Item>
        </Form>
      </Modal>
    )
  }

  render () {
    return (
      <div className={style.container}>
        {this.renderAddModal()}
        {this.renderModifyModal()}
        <div className={style['role-container']}>
          <ul className={style['role-list']}>
            {this.renderRoleList()}
          </ul>
          <Button type='link' block onClick={() => this.addButtonHandle()}>+添加角色</Button>
        </div>
        <div className={style['authorities-container']}>
          {this.renderAuthoritiesList()}
        </div>
      </div>
    )
  }
}

const mapState = mapStateToProps(function (state) {
  return {
    userInfo: state.basic.userInfo
  }
})

const mapDispatch = mapDispatchToProps(function (dispatch) {
  return {

  }
})

export default connect(mapState, mapDispatch)(RoleAuthorities)
